home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "c.h"
- #include "expr.h"
- #include "gen.h"
- #include "cglbdec.h"
-
- /*
- * 68000 C compiler
- *
- * Copyright 1984, 1985, 1986 Matthew Brandt.
- * all commercial rights reserved.
- *
- * This compiler is intended as an instructive tool for personal use. Any
- * use for profit without the written consent of the author is prohibited.
- *
- * This compiler may be distributed freely for non-commercial use as long
- * as this notice stays intact. Please forward any enhancements or questions
- * to:
- *
- * Matthew Brandt
- * Box 920337
- * Norcross, Ga 30092
- */
-
- TYP *head = 0;
- TYP *tail = 0;
- char *declid = 0;
- TABLE tagtable = {0,0};
- TYP stdconst = { bt_long, 1, 4, {0, 0}, 0, "stdconst"};
-
- int imax(i,j)
- int i,j;
- { return (i > j) ? i : j;
- }
-
- char *litlate(s)
- char *s;
- { char *p;
- p = xalloc(strlen(s) + 1);
- strcpy(p,s);
- return p;
- }
-
- TYP *maketype(bt,siz)
- int bt, siz;
- { TYP *tp;
- tp = xalloc(sizeof(TYP));
- tp->val_flag = 0;
- tp->size = siz;
- tp->type = bt;
- tp->sname = 0;
- tp->lst.head = 0;
- return tp;
- }
-
- int decl(table)
- TABLE *table;
- { switch (lastst) {
- case kw_char:
- head = tail = maketype(bt_char,1);
- getsym();
- break;
- case kw_short:
- head = tail = maketype(bt_short,2);
- getsym();
- break;
- case kw_int: case kw_long:
- head = tail = maketype(bt_long,4);
- getsym();
- break;
- case kw_unsigned:
- head = tail = maketype(bt_unsigned,4);
- getsym();
- if( lastst == kw_int )
- getsym();
- break;
- case id: /* no type declarator */
- head = tail = maketype(bt_long,4);
- break;
- case kw_float:
- head = tail = maketype(bt_float,4);
- getsym();
- break;
- case kw_double:
- head = tail = maketype(bt_double,8);
- getsym();
- break;
- case kw_enum:
- getsym();
- declenum(table);
- break;
- case kw_struct:
- getsym();
- declstruct(bt_struct);
- break;
- case kw_union:
- getsym();
- declstruct(bt_union);
- break;
- }
- }
-
- decl1()
- { TYP *temp1, *temp2, *temp3, *temp4;
- switch (lastst) {
- case id:
- declid = litlate(lastid);
- getsym();
- decl2();
- break;
- case star:
- temp1 = maketype(bt_pointer,4);
- temp1->btp = head;
- head = temp1;
- if(tail == NULL)
- tail = head;
- getsym();
- decl1();
- break;
- case openpa:
- getsym();
- temp1 = head;
- temp2 = tail;
- head = tail = NULL;
- decl1();
- needpunc(closepa);
- temp3 = head;
- temp4 = tail;
- head = temp1;
- tail = temp2;
- decl2();
- temp4->btp = head;
- if(temp4->type == bt_pointer &&
- temp4->val_flag != 0 && head != NULL)
- temp4->size *= head->size;
- head = temp3;
- break;
- default:
- decl2();
- break;
- }
- }
-
- decl2()
- { TYP *temp1;
- switch (lastst) {
- case openbr:
- getsym();
- temp1 = maketype(bt_pointer,0);
- temp1->val_flag = 1;
- temp1->btp = head;
- if(lastst == closebr) {
- temp1->size = 0;
- getsym();
- }
- else if(head != NULL) {
- temp1->size = intexpr() * head->size;
- needpunc(closebr);
- }
- else {
- temp1->size = intexpr();
- needpunc(closebr);
- }
- head = temp1;
- if( tail == NULL)
- tail = head;
- decl2();
- break;
- case openpa:
- getsym();
- temp1 = maketype(bt_func,0);
- temp1->val_flag = 1;
- temp1->btp = head;
- head = temp1;
- if( lastst == closepa) {
- getsym();
- if(lastst == begin)
- temp1->type = bt_ifunc;
- }
- else
- temp1->type = bt_ifunc;
- break;
- }
- }
-
- int alignment(tp)
- TYP *tp;
- { switch(tp->type) {
- case bt_char: return AL_CHAR;
- case bt_short: return AL_SHORT;
- case bt_long: return AL_LONG;
- case bt_enum: return AL_SHORT;
- case bt_pointer:
- if(tp->val_flag)
- return alignment(tp->btp);
- else
- return AL_POINTER;
- case bt_float: return AL_FLOAT;
- case bt_double: return AL_DOUBLE;
- case bt_struct:
- case bt_union: return AL_STRUCT;
- default: return AL_CHAR;
- }
- }
-
- int declare(table,al,ilc,ztype)
- /*
- * process declarations of the form:
- *
- * <type> <decl>, <decl>...;
- *
- * leaves the declarations in the symbol table pointed to by
- * table and returns the number of bytes declared. al is the
- * allocation type to assign, ilc is the initial location
- * counter. if al is sc_member then no initialization will
- * be processed. ztype should be bt_struct for normal and in
- * structure declarations and sc_union for in union declarations.
- */
- TABLE *table;
- int al;
- int ilc;
- int ztype;
- { SYM *sp, *sp1;
- TYP *dhead;
- int nbytes;
- nbytes = 0;
- decl(table);
- dhead = head;
- for(;;) {
- declid = 0;
- decl1();
- if( declid != 0) { /* otherwise just struct tag... */
- sp = xalloc(sizeof(SYM));
- sp->name = declid;
- sp->storage_class = al;
- while( (ilc + nbytes) % alignment(head)) {
- if( al != sc_member &&
- al != sc_external &&
- al != sc_auto) {
- dseg();
- genbyte(0);
- }
- ++nbytes;
- }
- if( al == sc_static)
- sp->value.i = nextlabel++;
- else if( ztype == bt_union)
- sp->value.i = ilc;
- else if( al != sc_auto )
- sp->value.i = ilc + nbytes;
- else
- sp->value.i = -(ilc + nbytes + head->size);
- sp->tp = head;
- if( sp->tp->type == bt_func &&
- sp->storage_class == sc_global )
- sp->storage_class = sc_external;
- if(ztype == bt_union)
- nbytes = imax(nbytes,sp->tp->size);
- else if(al != sc_external)
- nbytes += sp->tp->size;
- if( sp->tp->type == bt_ifunc &&
- (sp1 = search(sp->name,table->head)) != 0 &&
- sp1->tp->type == bt_func )
- {
- sp1->tp = sp->tp;
- sp1->storage_class = sp->storage_class;
- sp1->value.i = sp->value.i;
- sp = sp1;
- }
- else
- insert(sp,table);
- if( sp->tp->type == bt_ifunc) { /* function body follows */
- funcbody(sp);
- return nbytes;
- }
- if( (al == sc_global || al == sc_static) &&
- sp->tp->type != bt_func)
- doinit(sp);
- }
- if(lastst == semicolon)
- break;
- needpunc(comma);
- if(declbegin(lastst) == 0)
- break;
- head = dhead;
- }
- getsym();
- return nbytes;
- }
-
- int declbegin(st)
- int st;
- { return st == star || st == id || st == openpa ||
- st == openbr;
- }
-
- declenum(table)
- TABLE *table;
- { SYM *sp;
- TYP *tp;
- int evalue;
- if( lastst == id) {
- if((sp = search(lastid,tagtable.head)) == 0) {
- sp = xalloc(sizeof(SYM));
- sp->tp = xalloc(sizeof(TYP));
- sp->tp->type = bt_enum;
- sp->tp->size = 2;
- sp->tp->lst.head = sp->tp->btp = 0;
- sp->storage_class = sc_type;
- sp->name = litlate(lastid);
- sp->tp->sname = sp->name;
- getsym();
- if( lastst != begin)
- error(ERR_INCOMPLETE);
- else {
- insert(sp,&tagtable);
- getsym();
- enumbody(table);
- }
- }
- else
- getsym();
- head = sp->tp;
- }
- else {
- tp = xalloc(sizeof(tp));
- tp->type = bt_short;
- if( lastst != begin)
- error(ERR_INCOMPLETE);
- else {
- getsym();
- enumbody(table);
- }
- head = tp;
- }
- }
-
- enumbody(table)
- TABLE *table;
- { int evalue;
- SYM *sp;
- evalue = 0;
- while(lastst == id) {
- sp = xalloc(sizeof(SYM));
- sp->value.i = evalue++;
- sp->name = litlate(lastid);
- sp->storage_class = sc_const;
- sp->tp = &stdconst;
- insert(sp,table);
- getsym();
- if( lastst == comma)
- getsym();
- else if(lastst != end)
- break;
- }
- needpunc(end);
- }
-
- declstruct(ztype)
- /*
- * declare a structure or union type. ztype should be either
- * bt_struct or bt_union.
- */
- int ztype;
- { SYM *sp;
- TYP *tp;
- int slc;
- if(lastst == id) {
- if((sp = search(lastid,tagtable.head)) == 0) {
- sp = xalloc(sizeof(SYM));
- sp->name = litlate(lastid);
- sp->tp = xalloc(sizeof(TYP));
- sp->tp->type = ztype;
- sp->tp->lst.head = 0;
- sp->storage_class = sc_type;
- sp->tp->sname = sp->name;
- getsym();
- if(lastst != begin)
- error(ERR_INCOMPLETE);
- else {
- insert(sp,&tagtable);
- getsym();
- structbody(sp->tp,ztype);
- }
- }
- else
- getsym();
- head = sp->tp;
- }
- else {
- tp = xalloc(sizeof(TYP));
- tp->type = ztype;
- tp->sname = 0;
- tp->lst.head = 0;
- if( lastst != begin)
- error(ERR_INCOMPLETE);
- else {
- getsym();
- structbody(tp,ztype);
- }
- head = tp;
- }
- }
-
- structbody(tp,ztype)
- TYP *tp;
- int ztype;
- { int slc;
- slc = 0;
- tp->val_flag = 1;
- while( lastst != end) {
- if(ztype == bt_struct)
- slc += declare(&(tp->lst),sc_member,slc,ztype);
- else
- slc = imax(slc,declare(&tp->lst,sc_member,0,ztype));
- }
- tp->size = slc;
- getsym();
- }
-
- compile()
- /*
- * main compiler routine. this routine parses all of the
- * declarations using declare which will call funcbody as
- * functions are encountered.
- */
- { while(lastst != eof) {
- dodecl(sc_global);
- if( lastst != eof)
- getsym();
- }
- dumplits();
- }
-
- dodecl(defclass)
- int defclass;
- { int size;
- for(;;) {
- switch(lastst) {
- case kw_register:
- getsym();
- if( defclass != sc_auto && defclass != sc_member )
- error(ERR_ILLCLASS);
- goto do_decl;
- case id:
- if(defclass == sc_auto)
- return;
- /* else fall through to declare */
- case kw_char: case kw_int: case kw_short: case kw_unsigned:
- case kw_long: case kw_struct: case kw_union:
- case kw_enum: case kw_void:
- case kw_float: case kw_double:
- do_decl: if( defclass == sc_global)
- lc_static +=
- declare(&gsyms,sc_global,lc_static,bt_struct);
- else if( defclass == sc_auto)
- lc_auto +=
- declare(&lsyms,sc_auto,lc_auto,bt_struct);
- else
- declare(&lsyms,sc_auto,0,bt_struct);
- break;
- case kw_static:
- getsym();
- if( defclass == sc_member)
- error(ERR_ILLCLASS);
- if( defclass == sc_auto )
- lc_static +=
- declare(&lsyms,sc_static,lc_static,bt_struct);
- else
- lc_static +=
- declare(&gsyms,sc_static,lc_static,bt_struct);
- break;
- case kw_extern:
- getsym();
- if( defclass == sc_member)
- error(ERR_ILLCLASS);
- ++global_flag;
- declare(&gsyms,sc_external,0,bt_struct);
- --global_flag;
- break;
- default:
- return;
- }
- }
- }
-